package es.qb.deportivos.il.helper;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import org.primefaces.model.chart.CartesianChartModel;
import org.primefaces.model.chart.ChartSeries;

import es.qb.deportivos.bl.interfaces.EquipoBS;
import es.qb.deportivos.bl.interfaces.JugadorBS;
import es.qb.deportivos.bl.interfaces.JugadoresEquipoBS;
import es.qb.deportivos.bl.interfaces.PartidoBS;
import es.qb.deportivos.bl.interfaces.PuntosBS;
import es.qb.deportivos.exception.GeneralBusinessException;
import es.qb.deportivos.exception.GeneralPLException;
import es.qb.deportivos.il.domain.Equipo;
import es.qb.deportivos.il.domain.Jugador;
import es.qb.deportivos.il.domain.JugadoresEquipo;
import es.qb.deportivos.il.domain.Partido;
import es.qb.deportivos.il.domain.PartidoAlgoritmoLista;
import es.qb.deportivos.il.domain.PartidoCustom;
import es.qb.deportivos.il.domain.Puntos;
import es.qb.deportivos.util.Auditoria;
import es.qb.deportivos.util.Constants;
import es.qb.deportivos.util.Utilities;

public class PartidoHelper {
	/**
	 * Servicio de partido.
	 */
	private PartidoBS partidoBS;

	/**
	 * Servicio de partido.
	 */
	private PuntosBS puntosBS;

	/**
	 * Servicio de jugador.
	 */
	private JugadorBS jugadorBS;

	/**
	 * @return the partidoBS
	 */
	public PartidoBS getPartidoBS() {
		return partidoBS;
	}

	/**
	 * @param partidoBS
	 *            the partidoBS to set
	 */
	public void setPartidoBS(PartidoBS partidoBS) {
		this.partidoBS = partidoBS;
	}

	/**
	 * @return the puntosBS
	 */
	public PuntosBS getPuntosBS() {
		return puntosBS;
	}

	/**
	 * @param puntosBS
	 *            the puntosBS to set
	 */
	public void setPuntosBS(PuntosBS puntosBS) {
		this.puntosBS = puntosBS;
	}

	/**
	 * @return the jugadorBS
	 */
	public JugadorBS getJugadorBS() {
		return jugadorBS;
	}

	/**
	 * @param jugadorBS
	 *            the jugadorBS to set
	 */
	public void setJugadorBS(JugadorBS jugadorBS) {
		this.jugadorBS = jugadorBS;
	}

	private EquipoBS equipoBS;

	public EquipoBS getEquipoBS() {
		return equipoBS;
	}

	public void setEquipoBS(EquipoBS equipoBS) {
		this.equipoBS = equipoBS;
	}

	private JugadoresEquipoBS jugadoresEquipoBS;

	public JugadoresEquipoBS getJugadoresEquipoBS() {
		return jugadoresEquipoBS;
	}

	public void setJugadoresEquipoBS(JugadoresEquipoBS jugadoresEquipoBS) {
		this.jugadoresEquipoBS = jugadoresEquipoBS;
	}

	private JugadorHelper jugadorHelper;

	public JugadorHelper getJugadorHelper() {
		return jugadorHelper;
	}

	public void setJugadorHelper(JugadorHelper jugadorHelper) {
		this.jugadorHelper = jugadorHelper;
	}

	/**
	 * Carga la lista de Partidos.
	 * 
	 * @return List<Partido>
	 */
	public List<Partido> cargarPartidos() throws GeneralPLException {
		List<Partido> lstPartido = new ArrayList<Partido>();

		try {
			lstPartido = partidoBS.findAllOrderBy("fecha", false);
		} catch (GeneralBusinessException e) {
			throw new GeneralPLException(e);
		}
		return lstPartido;
	}

	public Partido buscarPartidoById(Integer partidoId, Integer jugadorId) throws GeneralPLException {
		try {

			Partido partido = new Partido();

			partido = partidoBS.findById(partidoId);

			if (jugadorId != null) {

				// Cargamos las puntuaciones de usuario logad
				Puntos puntos = new Puntos();

				List<JugadoresEquipo> lstJugadoresEquipos = new ArrayList<JugadoresEquipo>();

				lstJugadoresEquipos.addAll(partido.getEquipo1().getJugadoresEquipo());
				lstJugadoresEquipos.addAll(partido.getEquipo2().getJugadoresEquipo());

				Iterator<JugadoresEquipo> it = lstJugadoresEquipos.iterator();

				while (it.hasNext()) {

					JugadoresEquipo je = (JugadoresEquipo) it.next();

					// Cargamos las puntuaciones de usuario logado

					puntos.setPartido(partido);

					Jugador jugadorJurado = new Jugador();
					jugadorJurado.setId(jugadorId);

					puntos.setJugadorJurado(jugadorJurado);
					puntos.setJugadorVotado(je.getJugador());

					List<Puntos> lstPuntosJurado = puntosBS.buscarPuntos(puntos);

					if (lstPuntosJurado.size() > 0) {

						Puntos puntoJurado = lstPuntosJurado.get(0);
						je.setPuntos(puntoJurado.getPuntos());
					}

					// Cargamos las valoraciones
					puntos.setJugadorJurado(new Jugador());
					List<Puntos> lstPuntosValoracion = puntosBS.buscarPuntos(puntos);

					if (lstPuntosValoracion.size() > 0) {

						je.setVotos(lstPuntosValoracion.size());

						Iterator<Puntos> itValoracion = lstPuntosValoracion.iterator();

						Double sumValoracion = 0D;
						while (itValoracion.hasNext()) {

							Puntos puntosTemp = new Puntos();
							puntosTemp = (Puntos) itValoracion.next();
							sumValoracion += puntosTemp.getPuntos();

						}

						je.setValoracion(Double.valueOf(sumValoracion / lstPuntosValoracion.size()));

					} else {

						je.setValoracion(5.0D);
					}

				}

			}

			return partido;
		} catch (GeneralBusinessException e) {
			throw new GeneralPLException(e);
		}
	}

	/**
	 * Guarda una Jugador.
	 * 
	 * @return Jugador
	 */
	public Partido guardarPuntos(Partido partido) throws GeneralPLException {
		try {
			Utilities.setearAuditoriaAlta(partido);

			Jugador jugadorJurado = new Jugador();
			Auditoria auditoria = new Auditoria();
			jugadorJurado.setUsuario(auditoria.obtenerUsuario());
			List<Jugador> lstJugadores = jugadorBS.findByProperty("usuario", jugadorJurado.getUsuario());
			if (lstJugadores.size() > 0) {
				jugadorJurado = lstJugadores.get(0);
			}

			List<JugadoresEquipo> lstJugadoresEquipos = new ArrayList<JugadoresEquipo>();

			lstJugadoresEquipos.addAll(partido.getEquipo1().getJugadoresEquipo());
			lstJugadoresEquipos.addAll(partido.getEquipo2().getJugadoresEquipo());

			Iterator<JugadoresEquipo> it = lstJugadoresEquipos.iterator();

			while (it.hasNext()) {

				JugadoresEquipo je = new JugadoresEquipo();
				je = (JugadoresEquipo) it.next();

				// Inicializo Puntos
				Puntos puntos = new Puntos();

				// Jugador Jurado
				puntos.setJugadorJurado(jugadorJurado);

				// Jugador Votado
				puntos.setJugadorVotado(je.getJugador());

				// Partido
				puntos.setPartido(partido);

				List<Puntos> lstPuntos = puntosBS.buscarPuntos(puntos);

				// Puntos
				puntos.setPuntos(je.getPuntos());

				// Si no es mayor que cero no se guarda.
				if (lstPuntos.size() == 0 && Utilities.validarInteger(je.getPuntos())) {

					puntosBS.insert(puntos);
				}
			}

		} catch (GeneralBusinessException e) {
			throw new GeneralPLException(e);
		}
		return partido;
	}

	/**
	 * Guarda una Jugador.
	 * 
	 * @return Jugador
	 */
	public Partido insertarPartidos(Partido partido) throws GeneralPLException {
		try {
			Utilities.setearAuditoriaAlta(partido);
			partido = partidoBS.insert(partido);
		} catch (GeneralBusinessException e) {
			throw new GeneralPLException(e);
		}
		return partido;
	}

	public Boolean hasJugadoPartido(Partido partido, Integer jugadorLogadoId) throws GeneralPLException {

		Boolean bSalida = false;

		List<JugadoresEquipo> lstJugadoresEquipos = new ArrayList<JugadoresEquipo>();

		lstJugadoresEquipos.addAll(partido.getEquipo1().getJugadoresEquipo());
		lstJugadoresEquipos.addAll(partido.getEquipo2().getJugadoresEquipo());

		Iterator<JugadoresEquipo> it = lstJugadoresEquipos.iterator();

		while (it.hasNext() && !bSalida) {

			JugadoresEquipo je = new JugadoresEquipo();
			je = (JugadoresEquipo) it.next();

			if (je.getJugador().getId().equals(jugadorLogadoId)) {
				bSalida = true;
			}
		}

		return bSalida;
	}

	/**
	 * Crear Partido
	 * 
	 * @return Jugador
	 * @throws GeneralBusinessException
	 */
	public Boolean insertarPartido(PartidoAlgoritmoLista partido, Date fechaPartido) throws GeneralPLException, GeneralBusinessException {
		Boolean correcto = true;

		try {
			Partido partidoNuevo = new Partido();

			// Creamos los equipos ( blanco y negro )
			Equipo equipoBlanco = new Equipo();
			equipoBlanco.setBorradoLogico(false);
			Equipo insertEquipoBlanco = equipoBS.insert(equipoBlanco);

			Equipo equipoNegro = new Equipo();
			equipoNegro.setBorradoLogico(false);
			Equipo insertEquipoNegro = equipoBS.insert(equipoNegro);

			// Creamos los jugadoresEquipo Blanco
			for (Jugador jugadorEquipoBlanco : partido.getEquipo1().getListJugador()) {
				JugadoresEquipo jugadorEquip = new JugadoresEquipo();
				jugadorEquip.setBorradoLogico(false);
				jugadorEquip.setEquipo(insertEquipoBlanco);
				jugadorEquip.setJugador(jugadorEquipoBlanco);
				jugadoresEquipoBS.insert(jugadorEquip);
			}

			// Creamos los jugadoresEquipo Negro
			for (Jugador jugadorEquipoNegro : partido.getEquipo2().getListJugador()) {
				JugadoresEquipo jugadorEquip = new JugadoresEquipo();
				jugadorEquip.setBorradoLogico(false);
				jugadorEquip.setEquipo(insertEquipoNegro);
				jugadorEquip.setJugador(jugadorEquipoNegro);
				jugadoresEquipoBS.insert(jugadorEquip);
			}

			partidoNuevo.setBorradoLogico(false);
			partidoNuevo.setEquipo1(insertEquipoBlanco);
			partidoNuevo.setEquipo2(insertEquipoNegro);
			partidoNuevo.setFecha(fechaPartido);
			partidoBS.insert(partidoNuevo);

		} catch (Exception e) {
			correcto = false;
		}

		return correcto;
	}

	public Partido guardarGoles(Partido partido) throws GeneralBusinessException {

		Equipo equipoBlanco = partido.getEquipo1();
		for (JugadoresEquipo jugadorEquipo : equipoBlanco.getJugadoresEquipo()) {
			jugadoresEquipoBS.update(jugadorEquipo);
		}

		Equipo equipoNegro = partido.getEquipo2();
		for (JugadoresEquipo jugadorEquipoNegro : equipoNegro.getJugadoresEquipo()) {
			jugadoresEquipoBS.update(jugadorEquipoNegro);
		}

		if (equipoBlanco.getGoles() > equipoNegro.getGoles()) {
			equipoBlanco.setResultado(Constants.RESULTADO_GANADO);
			equipoNegro.setResultado(Constants.RESULTADO_PERDIDO);
		} else if (equipoBlanco.getGoles() < equipoNegro.getGoles()) {
			equipoNegro.setResultado(Constants.RESULTADO_GANADO);
			equipoBlanco.setResultado(Constants.RESULTADO_PERDIDO);
		} else {
			equipoNegro.setResultado(Constants.RESULTADO_EMPATADO);
			equipoBlanco.setResultado(Constants.RESULTADO_EMPATADO);
		}

		equipoBS.update(equipoBlanco);
		equipoBS.update(equipoNegro);
		return partido;
	}

	public CartesianChartModel estadisticaVisual(Integer jugador) throws GeneralBusinessException, GeneralPLException, NumberFormatException {

		CartesianChartModel categoryModel = new CartesianChartModel();

		List<PartidoCustom> listPartidosCustom = partidoBS.obtenerPartidosCustom(jugador);

		ChartSeries goles = new ChartSeries();
		goles.setLabel("Goles");

		Jugador jugadorObtenido = jugadorBS.findById(jugador);

		ChartSeries valoraciones = new ChartSeries();
		valoraciones.setLabel("Valoracion");
		for (PartidoCustom partidoCustom : listPartidosCustom) {
			goles.set(partidoCustom.getFechaPartido().toString(), partidoCustom.getGoles());
			valoraciones.set(partidoCustom.getFechaPartido().toString(),
					jugadorHelper.obtenerValoracionMedia(jugadorObtenido, new Integer(partidoCustom.getIdPartido().toString())).getValoracionMedia());
		}

		categoryModel.addSeries(goles);
		categoryModel.addSeries(valoraciones);

		return categoryModel;
	}
}